package fetch

import (
	"context"
	"go.uber.org/zap"
	. "monitor-agent/internal/common"
	. "monitor-agent/internal/report"
	. "monitor-agent/pkg/logging"
	"monitor-agent/registry"
	"time"
)

func handleResponse(r ReportServerClient, resp *ReportRsp, req *ReportReq, curTimes, resendTimes int) {
	ctx, cancel := context.WithTimeout(
		context.Background(),
		time.Millisecond*time.Duration(HandleTimeout),
	)
	defer cancel()

	// handle the response according the resp-code, might return in several situations
	switch resp.Code {
	case CodeSuccess:
		registry.SetSetting(resp.Setting)
	case CodeTransmitDenied:
		Logger().Error("backend refuse to receive agent report", zap.String("msg", resp.Msg))
	case CodeFailedToHandle:
		Logger().Error("backend failed to handle agent report", zap.String("msg", resp.Msg))
		registry.SetSetting(resp.Setting)
	case CodeFailedToTransmit:
		Logger().Error("failed to send report", zap.String("msg", resp.Msg), zap.Int("times", curTimes))
		resendReport(ctx, r, req, curTimes, resendTimes)
	case CodeFailedToStored:
		Logger().Error("backend failed to store report", zap.String("msg", resp.Msg), zap.Int("times", curTimes))
		registry.SetSetting(resp.Setting)
		resendReport(ctx, r, req, curTimes, resendTimes)
	default:
		Logger().Error("unsupported code", zap.Int32("code", resp.Code))
	}
}

func resendReport(ctx context.Context, r ReportServerClient, req *ReportReq, curTimes, resendTimes int) {
	if curTimes < resendTimes {
		handleResponse(r, sendReport(ctx, r, req), req, curTimes+1, resendTimes)
	} else {
		Logger().Error("failed to finish sending",
			zap.String("external_address", req.GetDimensions()[KeyPubAddress]),
			zap.String("internal_address", req.GetDimensions()[KeyLocAddress]),
		)
	}
}

func sendReport(ctx context.Context, r ReportServerClient, req *ReportReq) *ReportRsp {
	resp, err := r.Report(ctx, req)
	if err != nil {
		resp = &ReportRsp{Code: CodeFailedToTransmit, Msg: err.Error()}
	}
	return resp
}
